﻿using System;
using System.ComponentModel;
using System.Linq;

namespace Vk.Authorization
{
    public interface IAuthClient
    {
        /// <summary>
        ///     Идентификатор приложения Вконтакте
        /// </summary>
        int AppId { get; }

        /// <summary>
        ///     Разрешения, которые запрашиваются во время авторизации
        /// </summary>
        ApiAccessPermissions Permissions { get; }

        /// <summary>
        ///     Событие возникает при ошибке авторизации
        /// </summary>
        event EventHandler<AuthFailEventArgs> AuthFail;

        /// <summary>
        ///     Событие успешного завершения авторизации
        /// </summary>
        event EventHandler<AuthSuccessEventArgs> AuthSuccess;
    }

    public abstract class AuthClientBase : IAuthClient
    {
        /// <summary>
        ///     Ссылка на страницу авторизации
        /// </summary>
        protected string AuthPath
        {
            get
            {
                return "https://oauth.vk.com/authorize?" +
                       "client_id=" + AppId + "&" +
                       "redirect_uri=https://oauth.vk.com/blank.html&" +
                       (Permissions != null && Permissions.Values.Any() ? "scope=" + Permissions + "&" : string.Empty) +
                       "response_type=token&" +
                       "display=popup";
            }
        }

        public AuthClientBase(int appId, ApiAccessPermissions permissions = null)
        {
            AppId = appId;
            Permissions = permissions;
        }

        /// <summary>
        ///     Идентификатор приложения Вконтакте
        /// </summary>
        public int AppId { get; }

        /// <summary>
        ///     Разрешения, которые запрашиваются во время авторизации
        /// </summary>
        public ApiAccessPermissions Permissions { get; }

        #region Events   

        private readonly EventHandlerList _events = new EventHandlerList();

        protected static readonly object AuthSuccessEvent = new object();

        /// <summary>
        ///     Событие успешного завершения авторизации
        /// </summary>
        public event EventHandler<AuthSuccessEventArgs> AuthSuccess
        {
            add { _events.AddHandler(AuthSuccessEvent, value); }
            remove { _events.RemoveHandler(AuthSuccessEvent, value); }
        }

        protected static readonly object AuthFailEvent = new object();

        /// <summary>
        ///     Событие возникает при ошибке авторизации
        /// </summary>
        public event EventHandler<AuthFailEventArgs> AuthFail
        {
            add { _events.AddHandler(AuthFailEvent, value); }
            remove { _events.RemoveHandler(AuthFailEvent, value); }
        }

        protected void FireEvent<T>(object key, T e) where T : EventArgs
        {
            var handler = (EventHandler<T>) _events[key];
            if (handler != null)
                handler(this, e);
        }

        #endregion
    }

    public class AuthFailEventArgs : EventArgs
    {
        /// <summary>
        ///     Тип ошибки авторизации
        /// </summary>
        public enum FailType
        {
            /// <summary>
            ///     Ошибка, полученная в ответе VkAPI
            /// </summary>
            APIError,

            /// <summary>
            ///     Ошибка на стороне клиента
            /// </summary>
            LocalException
        }

        public FailType ErrorType { get; private set; }

        /// <summary>
        ///     Дополнительное сообщение
        /// </summary>
        public string Message { get; private set; }

        public AuthFailEventArgs(FailType errorType, string message)
        {
            ErrorType = errorType;
            Message = message;
        }
    }

    public class AuthSuccessEventArgs : EventArgs
    {
        /// <summary>
        ///     Обьект, в котором хранятся данные о сессии, полученные в результате успешной авторизации
        /// </summary>
        public VkSession Session { get; private set; }

        public AuthSuccessEventArgs(VkSession session)
        {
            Session = session;
        }
    }
}